<?php

namespace api\modules\v1\forms\buss;

use api\modules\common\services\UploadService;
use common\models\base\CommonStatus;
use common\models\base\Project;
use common\models\base\Tags;
use common\models\buss\CommonRelation;
use common\models\buss\Content;
use common\models\buss\Doctors;
use services\base\CommonRelationService;
use services\base\TagsService;
use services\buss\DoctorsService;
use services\member\MemberService;
use Yii;
use yii\base\Model;


class ContentForm extends Model
{
    /**
     * @var int $id ID
     * @var int $project_id 项目ID
     * @var int $type 类型
     * @var string $title 标题
     * @var string $content 内容
     * @var int $doctor_id 医生ID
     * @var int $c_id 分类ID
     * @var array $keyword 网址
     * @var array $tags 标签IDs
     * @var int $is_stream 是否投流【0不投流、1投流】
     * @var int $publish_status 发布状态【0下线、1正常】
     * @var array $attachment 文件
     * @var int $is_zip 是否下载zip【1是、0否】
     */
    public $id;
    public $project_id;
    public $type;
    public $title;
    public $content;
    public $doctor_id;
    public $c_id;
    public $keyword;
    public $tags;
    public $is_stream;
    public $publish_status;
    public $attachment;
    public $is_zip;

    /**
     * @var Content $_content
     * @var Project $_project
     * @var Doctors $_doctor
     * @var CommonStatus $_commonStatus
     * @var int[] $_tagIds
     * @var Tags[] $_tagList
     * @var Tags[] $_oldTagList
     * @var int[] $_addTagIds
     * @var int[] $_delTagIds
     * @var string[] $_addAttachment
     * @var string[] $_delAttachment
     * @var Project[] $_haveProjectList
     */
    protected $_content;
    protected $_project;
    protected $_doctor;
    protected $_commonStatus;
    protected $_tagIds;// 表单提交标签IDs【包含value=0,新增的】
    protected $_tagList;
    protected $_oldTagList;
    protected $_addTagIds;// 新增标签IDs
    protected $_delTagIds;// 删除标签IDs
    protected $_addAttachment;// 新增附件
    protected $_delAttachment;// 删除附件
    protected $_haveProjectList;// 权限下项目列表


    public function rules()
    {
        return [
            // 参数验证
            [['project_id', 'type', 'content', 'c_id', 'is_stream', 'publish_status'], 'required', 'message' => '{attribute}不能为空', 'on' => ['create']],
            [['id', 'project_id', 'type', 'content', 'c_id', 'is_stream', 'publish_status'], 'required', 'message' => '{attribute}不能为空', 'on' => ['edit']],
            [['id'], 'required', 'message' => '{attribute}不能为空', 'on' => ['delete']],
            [['id', 'is_zip'], 'required', 'message' => '{attribute}不能为空', 'on' => ['download']],

            [['id'], 'checkId', 'skipOnEmpty' => false, 'on' => ['edit', 'delete', 'download']],
            [['project_id'], 'checkProjectId', 'skipOnEmpty' => false, 'on' => ['create', 'edit']],
            [['type'], 'checkType', 'skipOnEmpty' => false, 'on' => ['create', 'edit']],
            [['title'], 'checkTitle', 'skipOnEmpty' => false, 'on' => ['create', 'edit']],
//            [['content'], 'checkContent', 'skipOnEmpty' => true, 'on' => ['create', 'edit']],
            [['doctor_id'], 'checkDoctorId', 'skipOnEmpty' => true, 'on' => ['create', 'edit']],
            [['c_id'], 'checkCid', 'skipOnEmpty' => true, 'on' => ['create', 'edit']],
            [['keyword'], 'checkKeyword', 'skipOnEmpty' => true, 'on' => ['create', 'edit']],
            [['tags'], 'checkTags', 'skipOnEmpty' => false, 'on' => ['create', 'edit']],
            [['is_stream'], 'checkIsStream', 'skipOnEmpty' => false, 'on' => ['create', 'edit']],
            [['publish_status'], 'checkPublishStatus', 'skipOnEmpty' => false, 'on' => ['create', 'edit']],
            [['attachment'], 'checkAttachment', 'skipOnEmpty' => false, 'on' => ['create', 'edit']],
            [['is_zip'], 'checkIsZip', 'skipOnEmpty' => false, 'on' => ['download']],
        ];
    }

    public function scenarios()
    {
        $scenarios = parent::scenarios();

        // 新增
        $scenarios['create'] = ['project_id', 'type', 'title', 'content', 'doctor_id', 'c_id', 'keyword', 'tags', 'is_stream', 'publish_status', 'attachment'];

        // 编辑
        $scenarios['edit'] = ['id', 'project_id', 'type', 'title', 'content', 'doctor_id', 'c_id', 'keyword', 'tags', 'is_stream', 'publish_status', 'attachment'];

        // 删除
        $scenarios['delete'] = ['id'];

        // 下载
        $scenarios['download'] = ['id', 'is_zip'];

        return $scenarios;
    }

    /**
     * @return array
     */
    public function attributeLabels()
    {
        return [
            'id' => 'ID',
            'project_id' => '项目ID',
            'type' => '类型',
            'title' => '标题',
            'content' => '内容',
            'c_id' => '分类',
            'keyword' => '关键词',
            'tags' => '标签',
            'is_stream' => '投流',
            'publish_status' => '状态',
            'attachment' => '附件',
        ];
    }

    /**
     * 检验内容ID
     * @param $attribute
     * @return void
     */
    public function checkId($attribute): void
    {
        if ($this->hasErrors()) {
            return;
        }

        $content = $this->getContent();
        if (!$content) {
            $this->addError($attribute, '内容不存在');
            return;
        }

        if ($content->status == Content::STATUS_DELETE) {
            $this->addError($attribute, '内容已删除');
            return;
        }
    }

    /**
     * 检验项目ID
     * @param $attribute
     * @return void
     */
    public function checkProjectId($attribute): void
    {
        if ($this->hasErrors()) {
            return;
        }

        $project = $this->getProject();
        if (empty($project)) {
            $this->addError($attribute, '项目不存在');
            return;
        }
        if ($project->status == Project::STATUS_DELETE) {
            $this->addError($attribute, '项目已删除');
            return;
        }
        if ($this->getScenario() == 'edit') {
            $content = $this->getContent();
            if ($this->project_id == $content->project_id) {// 未修改项目则不检验
                return;
            }
        }
        if (in_array($this->project_id, array_column($this->getHaveProjectList(), 'value')) === false) {
            $this->addError($attribute, '未绑定该项目，无权限操作');
            return;
        }
    }

    /**
     * 校验类型
     * @param $attribute
     * @return void
     */
    public function checkType($attribute): void
    {
        if ($this->hasErrors()) {
            return;
        }

        if (isset(Content::$types[$this->type]) === false) {
            $this->addError($attribute, '类型错误');
            return;
        }
    }

    /**
     * 校验标题
     * @param $attribute
     * @return void
     */
    public function checkTitle($attribute): void
    {
        if ($this->hasErrors()) {
            return;
        }
        if (empty($this->title) && in_array($this->type, [Content::TYPE_VIDEO, Content::TYPE_IMAGE])) {
            $this->addError($attribute, '标题不能为空');
            return;
        }
        $len = mb_strlen($this->title);
        if ($len > 50) {
            $this->addError($attribute, '标题长度错误【1-50个字】');
            return;
        }
    }

    /**
     * 校验医生
     * @param $attribute
     * @return void
     */
    public function checkDoctorId($attribute): void
    {
        if ($this->hasErrors()) {
            return;
        }
        if (empty($this->doctor_id)) {
            return;
        }
        $doctor = $this->getDoctor();
        if (empty($doctor)) {
            return;
        }
        $content = $this->getContent();
        if ($doctor->id == $content->doctor_id) {
            return;
        }
        if ($doctor->status == CommonStatus::STATUS_DELETE) {
            $this->addError($attribute, '医生已删除');
            return;
        }
        $doctorIds = array_column(DoctorsService::getEditCondition(), 'value');
        if (in_array($doctor->id, $doctorIds) === false) {
            $this->addError($attribute, '医生超出筛选范围');
            return;
        }
    }

    /**
     * 校验分类
     * @param $attribute
     * @return void
     */
    public function checkCid($attribute): void
    {
        if ($this->hasErrors()) {
            return;
        }

        $commonStatus = $this->getCommonStatus();
        if (empty($commonStatus)) {
            $this->addError($attribute, '分类不存在');
            return;
        }
        if ($commonStatus->status == CommonStatus::STATUS_DELETE) {
            $this->addError($attribute, '分类已删除');
            return;
        }
        if ($commonStatus->type != CommonStatus::TYPE_CONTENT) {
            $this->addError($attribute, '分类类型错误，非内容类型');
            return;
        }
    }

    /**
     * 校验关键词
     * @param $attribute
     * @return void
     */
    public function checkKeyword($attribute): void
    {
        if ($this->hasErrors()) {
            return;
        }

        $this->keyword = array_values(array_unique(array_filter($this->keyword)));
    }

    /**
     * 校验标签
     * @param $attribute
     * @return void
     */
    public function checkTags($attribute): void
    {
        if ($this->hasErrors()) {
            return;
        }
        try {
            $tagList = $this->getTagList();
        } catch (\Exception $e) {
            $this->addError($attribute, $e->getMessage());
            return;
        }
        $oldTagList = $this->getOldTagList();
        $newIds = array_column($tagList, 'id');
        $oldIds = array_column($oldTagList, 'id');
        // 新增标签
        $this->_addTagIds = array_diff($newIds, $oldIds);
        // 删除标签
        $this->_delTagIds = array_diff($oldIds, $newIds);
    }

    /**
     * 校验投流
     * @param $attribute
     * @return void
     */
    public function checkIsStream($attribute): void
    {
        if ($this->hasErrors()) {
            return;
        }

        if (isset(Content::$isStreams[$this->is_stream]) === false) {
            $this->addError($attribute, '投流参数错误');
            return;
        }
    }

    /**
     * 校验发布状态
     * @param $attribute
     * @return void
     */
    public function checkPublishStatus($attribute): void
    {
        if ($this->hasErrors()) {
            return;
        }

        if (isset(Content::$publishStatuss[$this->publish_status]) === false) {
            $this->addError($attribute, '发布状态参数错误');
            return;
        }
    }

    /**
     * 校验附件
     * @param $attribute
     * @return void
     */
    public function checkAttachment($attribute): void
    {
        if ($this->hasErrors()) {
            return;
        }
        if ($this->type == Content::TYPE_TXT) {
            $this->attachment = [];
            return;
        }
        if (empty($this->attachment)) {
            $this->addError($attribute, '附件不能为空');
            return;
        }
        if ($this->type == Content::TYPE_IMAGE) {
            if (count($this->attachment) > 20) {
                $this->addError($attribute, '图片最多20张');
                return;
            }
        } elseif(count($this->attachment) > 1) {
            $this->addError($attribute, '视频最多1条');
            return;
        }
        // 检验文件格式
        $errorFile = [];
        $checkTypeArr = $this->type == Content::TYPE_IMAGE ? UploadService::$imageTypeArr : UploadService::$videoTypeArr;
        foreach ($this->attachment as $row) {
            if (in_array(substr($row, strripos($row,'.')), $checkTypeArr) == false) {
                $errorFile[] = $row;
            }
        }
        if ($errorFile) {
            $errorFiles = implode(',', $errorFile);
            $this->addError($attribute, "【{$errorFiles}】文件格式错误");
            return;
        }

        $oldAttachment = $this->getContent()->attachment ?? [];
        $this->_addAttachment = array_diff($this->attachment, $oldAttachment);
        $this->_delAttachment = array_diff($oldAttachment, $this->attachment);
    }

    /**
     * 校验is_zip
     * @param $attribute
     * @return void
     */
    public function checkIsZip($attribute): void
    {
        if ($this->hasErrors()) {
            return;
        }
        if (in_array($this->is_zip, [0, 1]) === false) {
            $this->addError($attribute, '参数错误【is_zip值有误】');
            return;
        }
        $content = $this->getContent();
        if ($this->is_zip == 0 && $content->type != Content::TYPE_VIDEO) {
            $this->addError($attribute, '非视频内容无法下载');
            return;
        }
    }

    /**
     * 获取内容信息
     * @return Content|null
     */
    public function getContent(): ?Content
    {
        if (empty($this->_content)) {
            $this->_content = Content::findOne($this->id);
        }

        return $this->_content;
    }

    /**
     * 获取项目信息
     * @return Project|null
     */
    public function getProject(): ?Project
    {
        if (empty($this->_project)) {
            $this->_project = Project::findOne($this->project_id);
        }

        return $this->_project;
    }

    /**
     * 获取内容信息
     * @return Doctors|null
     */
    public function getDoctor(): ?Doctors
    {
        if (empty($this->_doctor)) {
            $this->_doctor = Doctors::findOne($this->doctor_id);
        }
        return $this->_doctor;
    }

    /**
     * 获取内容信息
     * @return Content|null
     */
    public function getCommonStatus(): ?CommonStatus
    {
        if (empty($this->_commonStatus)) {
            $this->_commonStatus = CommonStatus::findOne($this->c_id);
        }

        return $this->_commonStatus;
    }

    /**
     * 获取新标签列表
     * @return Tags[]
     */
    public function getTagList(): array
    {
        if (is_null($this->_tagList)) {
            $newIds = $addTagName = [];
            $this->tags = $this->tags ?: [];
            foreach ($this->tags as $row) {
                if (empty($row['value']) && in_array($row['label'], $addTagName) === false) {
                    $addTagName[] = $row['label'];
                }
                if ($row['value']) {
                    $newIds[] = $row['value'];
                }
            }
            if ($addTagName) {
                if ($invalidTags = TagsService::getInvalidListByName(Tags::TYPE_CONTENT, $addTagName)) {
                    $invalidTagNames = implode(',', array_column($invalidTags, 'name'));
                    throw new \Exception("标签【{$invalidTagNames}】被禁用，无法操作");
                }

                $service = new TagsService();
                $service->createTags([
                    'name' => implode(',', $addTagName),
                    'type' => Tags::TYPE_CONTENT,
                ]);
                $addIds = array_column(TagsService::getNormalListByName(Tags::TYPE_CONTENT, $addTagName), 'id');
                $newIds = array_merge($newIds, $addIds);
            }
            $this->_tagIds = $newIds;
            $this->_tagList = TagsService::getNormalListByIds(CommonRelation::TYPE_CONTENT, $this->_tagIds);
        }

        return $this->_tagList;
    }

    /**
     * 获取原标签列表
     * @return Tags[]
     */
    public function getOldTagList(): array
    {
        if (empty($this->_oldTagList)) {
            $this->_oldTagList = $this->getScenario() == 'edit'
                ? TagsService::getNormalListByIds(CommonRelation::TYPE_CONTENT, CommonRelationService::getContentTagIds($this->id))
                : [];
        }

        return $this->_oldTagList;
    }

    /**
     * 获取新增标签IDs
     * @return Tags[]
     */
    public function getAddTagIds(): array
    {
        return $this->_addTagIds ?: [];
    }

    /**
     * 获取删除标签IDs
     * @return Tags[]
     */
    public function getDelTagIds(): array
    {
        return $this->_delTagIds ?: [];
    }

    /**
     * 获取新增附件
     * @return array
     */
    public function getAddAttachment(): array
    {
        return $this->_addAttachment ?: [];
    }

    /**
     * 获取删除附件
     * @return array
     */
    public function getDelAttachment(): array
    {
        return $this->_delAttachment ?: [];
    }

    /**
     * 获取账号信息
     * @return Project[]
     */
    public function getHaveProjectList(): array
    {
        if (empty($this->_haveProjectList)) {
            $this->_haveProjectList = MemberService::getProjectEditCondition();
        }

        return $this->_haveProjectList;
    }
}
